///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2007-2009 ILOG, S.A.
//  All Rights Reserved.
//  The following is ILOG Source Code.  No modifications may be made to the  
//  ILOG Source Code.  Any usage of the ILOG Source Code is subject to 
//  the terms and conditions of the ILOG End User License Agreement   
//  applicable to this ILOG software product.
//
///////////////////////////////////////////////////////////////////////////////

package ilog.gauges.rectangular
{
  import ilog.gauges.gaugesClasses.LogScale;
  import ilog.gauges.gaugesClasses.rectangular.IRectangularNumericScale;

  /**
   * The <code>RectangularLogScale</code> class represents the logarithmic scale 
   * for rectangular gauges. This class can be used to populate the <i>scales</i> 
   * array of the gauge.
   *  
   * @see ilog.gauges.rectangular.RectangularScale
   * 
   * @includeExample examples/RectangularGaugeExample.mxml -noswf
   */
  public class RectangularLogScale extends LogScale implements IRectangularNumericScale
  {
   
    /**
     * Constructor.
     */
    public function RectangularLogScale()
    {
    }
    
    private var _offset:Number = 0;

    [Bindable]
    [Inspectable(environment="none")]       

    /**
     *  @copy ilog.gauges.gaugesClasses.rectangular.IRectangularScale#offset
     */
    public function get offset():Number
    {
      return _offset;
    }

    /**
     * @private
     */
    public function set offset(value:Number):void
    {
      if (value != _offset) {
        _offset = value;
        invalidateElements();
      }
    }

    private var _length:Number = 0;

    [Bindable]
    [Inspectable(environment="none")]       

    /**
     *  @copy ilog.gauges.gaugesClasses.rectangular.IRectangularScale#length
     */
    public function get length():Number
    {
      return _length;
    }

    /**
     * @private
     */
    public function set length(value:Number):void
    {
      if (value != _length) {
        _length = value;
        invalidateElements();
      }
    }
    
    /**
     *  @copy ilog.gauges.gaugesClasses.rectangular.IRectangularScale#positionForValue
     */
    public function positionForValue(value:Object):Number
    {
      var v:Number = value as Number;      
      if (computedMaximum < computedMinimum || v <= computedMinimum || v < 1 || isNaN(v))
        v = computedMinimum;        
      if (v >= computedMaximum)
        v = computedMaximum;
      v = Math.log(v) / Math.LN10;
      var sv:Number = Math.log(computedMinimum) / Math.LN10;
      var ev:Number = Math.log(computedMaximum) / Math.LN10;
      return _offset + ((v - sv) * _length) / (ev - sv); 
    }

    /**
     *  @copy ilog.gauges.gaugesClasses.rectangular.IRectangularScale#valueForPosition
     */
    public function valueForPosition(position:Number):Object
    {
      // limit positions, return the extremum
      if (position < _offset)
        return computedMinimum;
      if (position > _offset + _length)
        return computedMaximum;
      var sv:Number = Math.log(computedMinimum) / Math.LN10;
      var ev:Number = Math.log(computedMaximum) / Math.LN10;
      return Math.pow(10, sv + (position - _offset) * (ev - sv) / _length);
    }
    
    /**
     *  @copy ilog.gauges.gaugesClasses.rectangular.IRectangularScale#positionInRange
     */
    public function positionInRange(position:Number):Boolean
    {
      return (position >= _offset && position <= _offset + _length);
    }         
  }
}
